package com 
{
	import data.GCBuildingData;
	import data.GCCityData;
	
	/**
	 * A logical representation for the city in our game. Cities consists
	 * of static data, like name and resource that can be harvested and
	 * player data, which consists of buildings they have constructed, total
	 * workers stationed at the city, and inventory.
	 * @author Jason Won
	 */
	public class GCCity 
	{
		/*
		 * The unique id for this location.
		 */
		private var _cityId:uint;
		
		/*
		 * A list of the ids of all possible goods that can be produced.
		 * This is static information, will not change based on any player
		 * actions.
		 */
		private var _resources:Vector.<uint>;
		
		/*
		 * A list of the ids of all possible buildings that a player
		 * can construct at this city. Partly depends on the types of resources
		 * that are available.
		 * 
		 * Also keep a list of the buildings that they have already built.
		 * 
		 * These lists are all related to a unique building id assigned to each
		 * structure in our game.
		 */
		private var _allBuildingsCanConstruct:Vector.<uint>;
		private var _allBuildingsBuilt:Vector.<uint>;
		
		/*
		 * Keep a list of all buildings this player has constructed at this
		 * city. These are references to the actual GCCityBuildings objects.
		 */
		private var _constructedBuildings:Vector.<GCCityBuilding>;
		
		/*
		 * The inventory that the player has at this city, stored in their warehouse.
		 * Is null if no warehouse has been constructed.
		 */
		public var _warehouse:GCInventory;
		
		/**
		 * The inventory that holds all the sales that the player has put up in this city
		 */
		public var _playerSales:GCInventory;
		
		/*
		 * The total number of workers that are stationed at this city. The workers
		 * can be at buildings or can just be idle.
		 */
		public var _totalWorkers:uint;
		private var _idleWorkers:uint;
		
		/**
		 * Construct a new city. This will only be called on game startup. No player actions will result in
		 * a new city to be constructed. If a player does not have any data contained in a particular city,
		 * we simply initialize parameters to be empty or null.
		 * 
		 * @param	cityId
		 * @param	buildings
		 * @param	resources
		 * @param	warehouse
		 */
		public function GCCity(cityId:int, buildings:Vector.<GCCityBuilding>, totalWorkers:uint, warehouse:GCInventory, playerSales:GCInventory) 
		{
			this._cityId = cityId;
			
			this._constructedBuildings = (buildings == null) ? new Vector.<GCCityBuilding>() : buildings;
			this._warehouse = warehouse;
			this._playerSales = playerSales;
			this._totalWorkers = totalWorkers;
			
			_allBuildingsBuilt = new Vector.<uint>();
			if (buildings != null)
			{
				for each(var bldg:GCCityBuilding in buildings)
				{
					_allBuildingsBuilt.push(bldg.buildingId);
				}
			}
			
			initStaticData();
		}
		
		/**
		 * Function to construct a new building at this city. Doing so will
		 * add to the list of buildings objects and modify the list of
		 * ids keeping track of whats left to be built and what has been already
		 * built.
		 */
		public function constructNewBuilding(buildingId:int):void
		{
			var newBuilding:GCCityBuilding = new GCCityBuilding(buildingId, 0);
			
			if (GCBuildingData.BUILDING_WAREHOUSE == buildingId)
			{
				_warehouse = new GCInventory(new Vector.<GCItem>(), 0, GCBuildingData.WAREHOUSE_CAPACITY);
				_playerSales = new GCInventory(new Vector.<GCItem>(), 0, GCBuildingData.WAREHOUSE_CAPACITY);
			}
			
			_constructedBuildings.push(newBuilding);
			_allBuildingsBuilt.push(buildingId);
		}
		
		/** Get Functions **/
		/**
		 * Returns the name of the city
		 * 
		 * @return
		 */
		public function getName():String
		{
			return GCCityData.getNameFromId(_cityId);
		}
		
		public function getId():int
		{
			return _cityId;
		}
		
		/**
		 * Gets a list of the resources that can be harvested from
		 * this city.
		 * 
		 * @return
		 */
		public function getResources():Vector.<uint>
		{
			return _resources.concat();
		}
		
		/**
		 * Gets the list of all building ids available to the player.
		 * 
		 * @return
		 * 		Gives back a COPY of the vector of building ids
		 */
		public function getAllPossibleBuildings():Vector.<uint>
		{
			return _allBuildingsCanConstruct.concat();
		}
		
		/**
		 * Gets the list of all building ids that the player has already
		 * constructed.
		 * 
		 * @return
		 */
		public function getAllAlreadyConstructed():Vector.<uint>
		{
			return _allBuildingsBuilt.concat();
		}
		
		/**
		 * Gets a list of the actual GCCityBuilding objects that have
		 * been constructed by the player.
		 * 
		 * @return
		 * 
		 */
		public function getConstructedBuildings():Vector.<GCCityBuilding>
		{
			return _constructedBuildings;//_constructedBuildings.concat();
		}
		
		public function getInventoryFromCity():GCInventory
		{
			return _warehouse;
		}
		
		public function getSalesFromCity():GCInventory
		{
			return _playerSales;
		}
		
		/**
		 * Get the total number of workers who are at this city.
		 */
		public function get totalWorkers():uint
		{
			return this._totalWorkers;
		}
		
		public function get idleWorkers():uint
		{
			return this._idleWorkers;
		}
		
		/**
		 * Change the total number of workers who are at this city.
		 * 
		 * @param newTotal
		 * 		New number of workers at city.
		 */
		public function set totalWorkers(newTotal:uint):void
		{
			this._totalWorkers = newTotal;
		}
		
		public function set idleWorkers(newTotal:uint):void
		{
			this._idleWorkers = newTotal;
		}
		
		/**
		 * Function to initialize the list of buildings that can be constructed at this
		 * city. It will depend on the resources and perhaps the city location and even
		 * what buildings have already been constructed (if doing tiered structures.)
		 */
		private function initStaticData():void
		{
			_allBuildingsCanConstruct = new Vector.<uint>();
			
			/*
			 * Players can always build a regualr warehouse at a city
			 */
			_allBuildingsCanConstruct.push(GCBuildingData.BUILDING_WAREHOUSE);
			 
			_resources = GCCityData.getResourcesFromId(this._cityId);
			for each (var resource:uint in _resources)
			{
				for (var i:uint = 0; i < GCBuildingData.NUM_BUILDINGS; i++)
				{
					if (GCBuildingData.getResourceFromId(i) == resource)
					{
						_allBuildingsCanConstruct.push(i);
					}
				}
			}
		}
	}

}